﻿Namespace IMDB
    Public Class Search
        Public Class GetImdbIdByTitleResult
            Public Id As String
            Public Html As String
        End Class
        Public Shared Function GetImdbIdByTitle(ByVal title As String) As GetImdbIdByTitleResult
            Dim uriSearch As Uri = GetSearchTitleUri(title) ' String.Format("http://www.imdb.com/find?s=tt&q={0}", title.Trim.Replace(" "c, "+"c))

            'first, issue a webrequest and see if we get the title page immediately
            Dim clsPage As GetPageResult = GetPage(uriSearch)

            Dim clsRet As New GetImdbIdByTitleResult
            If OpenMediaInfo.IMDB.Manager.IsImdbTitlePage(clsPage.Uri) Then
                clsRet.Id = OpenMediaInfo.IMDB.Manager.GetImdbIdFromUri(clsPage.Uri)
            Else
                clsRet.Id = Nothing
            End If
            clsRet.Html = clsPage.Html
            Return clsRet
        End Function
        Public Shared Function GetAllTitlesFromSearchResult(ByVal uri As Uri) As Generic.List(Of FoundTitle)
            Dim clsPage As GetPageResult = GetPage(uri)
            Return GetAllTitlesFromSearchResult(clsPage.Html)
        End Function
        Public Shared Function GetAllTitlesFromSearchResult(ByVal html As String) As Generic.List(Of FoundTitle)
            Return GetAllTitlesFromSearchResultWorker(html, New FoundTitleType() {FoundTitleType.Popular, FoundTitleType.ExactMatch, FoundTitleType.PartialMatch, FoundTitleType.ApproxMatch})
        End Function
        Public Shared Function GetAllTitlesFromSearchResult(ByVal html As String, ByVal type As FoundTitleType) As Generic.List(Of FoundTitle)
            Return GetAllTitlesFromSearchResultWorker(html, New FoundTitleType() {type})
        End Function

        Private Shared Function GetAllTitlesFromSearchResultWorker(ByVal html As String, ByVal types() As FoundTitleType) As Generic.List(Of FoundTitle)
            Dim clsHtml As MIL.Html.HtmlDocument
            clsHtml = MIL.Html.HtmlDocument.Create(html)

            Dim aRet As New Generic.List(Of FoundTitle)
            For Each udtType As FoundTitleType In types
                Select Case udtType
                    Case FoundTitleType.ApproxMatch
                        aRet.AddRange(GetAllTitlesFromDoc(clsHtml, "titles (approx matches)", FoundTitleType.ApproxMatch))
                    Case FoundTitleType.ExactMatch
                        aRet.AddRange(GetAllTitlesFromDoc(clsHtml, "titles (exact matches)", FoundTitleType.ExactMatch))
                    Case FoundTitleType.PartialMatch
                        aRet.AddRange(GetAllTitlesFromDoc(clsHtml, "titles (partial matches)", FoundTitleType.PartialMatch))
                    Case FoundTitleType.Popular
                        aRet.AddRange(GetAllTitlesFromDoc(clsHtml, "popular titles", FoundTitleType.Popular))
                    Case Else
                        Throw New NotImplementedException
                End Select
            Next
            Return aRet
        End Function

        Private Shared Function GetAllTitlesFromDoc(ByVal doc As MIL.Html.HtmlDocument, ByVal caption As String, ByVal type As FoundTitleType) As Generic.List(Of FoundTitle)
            Dim aRet As New Generic.List(Of FoundTitle)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, caption)
            If clsElement Is Nothing Then Return aRet

            Dim clsTable As MIL.Html.HtmlElement = Nothing
            If clsElement.Next IsNot Nothing Then
                If clsElement.Next.Next IsNot Nothing Then
                    If TypeOf clsElement.Next.Next Is MIL.Html.HtmlElement Then
                        clsTable = CType(clsElement.Next.Next, MIL.Html.HtmlElement)
                    End If
                End If
            End If
            If clsTable IsNot Nothing Then
                Dim clsRowNode As MIL.Html.HtmlNode = clsTable.FirstChild
                While clsRowNode IsNot Nothing
                    Dim clsRow As MIL.Html.HtmlElement = TryCast(clsRowNode, MIL.Html.HtmlElement)
                    If clsRow IsNot Nothing AndAlso clsRow.Name IsNot Nothing AndAlso clsRow.Name.ToLower = "tr" Then
                        Dim clsQ As MIL.Html.HtmlNode
                        clsQ = clsRow.FirstChild
                        If clsQ IsNot Nothing Then clsQ = clsQ.Next
                        If clsQ IsNot Nothing Then clsQ = clsQ.Next
                        If clsQ IsNot Nothing Then clsQ = clsQ.FirstChild
                        While clsQ IsNot Nothing
                            Dim clsEl As MIL.Html.HtmlElement = TryCast(clsQ, MIL.Html.HtmlElement)
                            If clsEl IsNot Nothing Then
                                If clsEl.Name = "a" Or clsEl.Name = "A" Then
                                    Dim clsItem As New FoundTitle
                                    clsItem.Name = clsEl.Text
                                    clsItem.Type = type
                                    Dim clsYear As MIL.Html.HtmlText = TryCast(clsEl.Next, MIL.Html.HtmlText)
                                    If clsYear IsNot Nothing Then
                                        clsItem.Year = ExtractYearFromText(clsYear.Text)
                                    End If
                                    For Each clsA As MIL.Html.HtmlAttribute In clsEl.Attributes
                                        If clsA.Name.ToLower = "href" Then
                                            clsItem.Id = Manager.GetImdbIdFromUri(clsA.Value)
                                            clsItem.Uri = Manager.GetUriFromId(clsItem.Id)
                                            Exit For
                                        End If
                                    Next
                                    aRet.Add(clsItem)
                                    Exit While
                                End If
                            End If
                            clsQ = clsQ.Next
                        End While
                    End If

                    clsRowNode = clsRowNode.Next
                End While
            End If
            Return aRet
        End Function
        Private Shared Function ExtractYearFromText(ByVal text As String) As String
            '(1234) or (1234)(...)
            text = text.Replace(" ", String.Empty)
            If Not text.StartsWith("("c) Then Return String.Empty
            Dim iPos As Integer = text.IndexOf(")"c)
            If iPos < 0 Then Return String.Empty
            text = text.Substring(1, iPos - 1)
            Return text
        End Function

        Public Class FoundTitle
            Public Id As String
            Public Name As String
            Public Year As String
            Public Type As FoundTitleType
            Public Uri As Uri
        End Class
        Public Enum FoundTitleType
            ExactMatch
            Popular
            PartialMatch
            ApproxMatch
        End Enum

        Private Shared Function GetPage(ByVal uri As Uri) As GetPageResult
            Dim clsRet As New GetPageResult
            Dim clsWR As System.Net.WebRequest = Net.WebRequest.Create(uri)
            Using clsRes As System.Net.WebResponse = clsWR.GetResponse
                clsRet.Uri = clsRes.ResponseUri
                Using clsResStream As IO.Stream = clsRes.GetResponseStream
                    Using clsSR As New IO.StreamReader(clsResStream)
                        clsRet.Html = clsSR.ReadToEnd
                    End Using
                End Using
            End Using
            Return clsRet
        End Function
        Private Class GetPageResult
            Public Uri As Uri
            Public Html As String
        End Class

        Public Shared Function GetSearchTitleUri(ByVal title As String) As Uri
            title = CleanTitleForSearch(title)
            Dim strUrl As String = "http://www.imdb.com/find?s=tt&q={0}"
            title = title.Replace(" "c, "+"c)
            Return New Uri(String.Format(strUrl, title))
        End Function
        Public Shared Function CleanTitleForSearch(ByVal title As String) As String
            If title.ToLower.EndsWith(", the") Then
                title = "The " & title.Substring(0, title.Length - 5).Trim
            End If
            Return title
        End Function
    End Class


End Namespace